"So is there any essential skill needed to be a programmer? Different domains obviously have different requirements but ultimately is there some commonality to writing code regardless of domain?"
Peters answer to this _really_ resonated with me - his first two sentences were "You've got to be able to make progress and then improve on it. That's all you need to be able to do in life."
How would you answer this question?
Specifically:
- Never say "Got it" or "OK" when someone is explaining a problem or solution and you don't follow. It feels awkward to say "Sorry, I'm still not following. Do you mean that when..." five times in the same conversation but it is worth your time and embarrassment to come away with a correctly framed and well understood situation. Otherwise you will figure out what they meant after wasting hours/days/months solving the wrong thing.
- You'll be faced with situations where your colleagues/organization expect you to implement solutions you think are not the best. Understand that "the best way" for the team or business is not necessarily the same as "the best way" for you personally or "the best way" overall. You are likely missing some context about the choice. Be mindful of reputation risks, time costs and maintenance costs involved in changing the approach.
When you're asked to code something you don't agree with (including ethical issues) your options include: silently accept their approach, refuse to do their approach, propose an approach (with conversation or code) and gracefully accept the result, or find another job. Be aware that different organizations will react differently to those approaches. Under no circumstances should you fall into the trap of spending a week to convince the team to adopt a change that would save a week of costs.
To be a good programmer, if I have to pick only one "skill" I would pick systemic thinking/understanding. This starts with the ability to learn and eventually understand how a system works. The next level is the ability to create a working model of that system in ones mind. Someone who can do that will be very successful at programming anything in any language on any platform given sufficient documentation.
Being able to clearly explain why your solution will solve a given problem better than the alternative and listen to your colleagues when their suggestion is better than yours, will save you an incredible amount of frustration. It is in my opinion the most important skill I have learned
- Asking why when debugging
Finding the code that's causing a bug is only the first step. The next is preventing a similar one happening again. By constantly asking "why was this choice made", you end up finding the actual weak points in both the code and your process. Whether it's because a hack some other place forced you to write another hack, that then failed or because there was a deadline so the commit was made at 3am, there is an important lesson to be had. If you combine that with good communication, you can talk to the team about changing things, so you avoid creating similar bugs in the future. (Pro-tip: 99% of bugs are there because there wasn't time to do things better)
A curious thing that happens every time I write code is that some unexpected error occurs. Sometimes it's trivial stuff, other times it's deep structure. Either way, you have to be bothered to make changes and test them. Sometimes this tree gets very very deep. See an error, Google it, find an example that mentions a new keyword, explore that cave for a day, return to previous branch, etc.
Something about this is related to addiction, I think I'm somehow fortunate to be addicted to something useful rather than just some molecule.
To be a good programmer: very much depends on your area of expertise. Most of them need good communication skills, some machine-level understanding, some math or algorithm skills, some require high velocity / long hours... It really is a very diverse field.
But like for most jobs, frustration tolerance gets you surprisingly far.
Good logical reasoning, and spatial thinking/skills, ability to build up complex systems from smaller ones, and ability to understand/debug how complex systems work, and no 'magical thinking', but ability to analyze things logically.
I am seeing here a bunch of answers that mention 'communication', 'write docs', etc... etc but those are essential skills for any employee in a large company, no matter what the discipline is.
They are not core engineering skills per se (though they are necessary to perform in a large company). If you can't code, or don't understand concepts your communication skills will not help you that much. Maybe become a PM, or some kind of manager, but not an engineer.
P.s I know communication is not core, as i have worked with many 'brilliant' engineers that they had poor communication skills due to be foreigners, or just personality quirks. While that will hamper their ability to get promoted to managers, or architects, they all were respected and did well as engineers.
Although high general intelligence is common among hackers, it is not the sine qua non one might expect. Another trait is probably even more important: the ability to mentally absorb, retain, and reference large amounts of ‘meaningless’ detail, trusting to later experience to give it context and meaning. A person of merely average analytical intelligence who has this trait can become an effective hacker, but a creative genius who lacks it will swiftly find himself outdistanced by people who routinely upload the contents of thick reference manuals into their brains.
I draw on whiteboards, in moleskins, on printer paper, on the back of resumes... anywhere and everywhere. I do this because I need to convey complex ideas to important teams who are NOT programmers: Product, Marketing, People Ops, and the C-suite.
Helping people understand my ideas through illustration creates buy-in from them and trust in me. You can be a great programmer, but if people don't know and don't trust in what you're doing you'll never be given the space to execute.
"Programmers are not to be measured by their ingenuity and their logic but by the completeness of their case analysis."
Well-engineered programs cover all the cases: they handle what they must handle, and have an answer for the rest which is better than "oh shoot, didn't think of that".
The main programmer skill is remembering to ask yourself, "under what conditions won't this work?" or "what inputs or situations break this?" and being able to come up with excellent answers.
Also, asking this question: "though this appears to work, where are all the requirements (language, library, platform, ...) coming from which make it work, and are any missing?"
That's not all you need, obviously. No one thing is the magic bullet which will make you a better programmer. But the worst programmers I've worked with only write code which works on their machine, for their specific use-case.
2. Prioritization - Learn to prioritize and sometimes to say "NO" to people.
3. Delegation - One cannot do everything by oneself. Learn to delegate and get help from others.
4. Whenever you do some task, always question why am I doing this, why this needs to be done in a certain manner and learn all the background(domain specific) knowledge related to the task.
5. Learn how to debug - I cannot stress enough how important this is. Most of the time you would spend maintaining, coding, and changing, legacy/existing code written by someone else. If you do not know how to debug and follow the trail like Enola Holmes, you'd always have to depend on the help of others which is very inconvenient for you as well as for others.
Apart from that as mentioned in the other answers it's always good to be a smart cookie, but it's not essential.
Git and version control, learn them as in depth as you have time for. Every decent dev environment has these and the amount of people lacking this basic knowledge is staggering.
Bash/Linux or powershell/windows same thing. You can get an amazing amount of things done with shell scripting in your OS. Unless you have an insane amount of time I would pick one and learn in depth. These are rich systems.
A dynamic programming language in depth. There are so many concepts that will transfer between languages that if you know one in depth, you'll be able to pick another one up pretty fast as it's just semantics at that point.
SQL, this is an essential part of dev life and you will understand ORMs and data management better.
The personal skills:
Communication obviously. This is such a vague term and I think is abused as people just say 'lERn to CoMmUNicate' with no actionable advice. Things like politeness, small talk, respect for other's etc.
At the same time know when to be honest. I've seen the best communicators tell management exactly what management wants to hear over and over and projects kept being behind or over budget because there was a dysfunctional connection between the manager and the engineer who kept B.S.ing them with what they wanted to hear and the nitwit manager eating it up and for some reason never learning.
Systems reasoning, learn to understand the system from the line of code up through the stacks to the whole. Sounds cliche and it is but it will make you a better programmer.
Debugging. This will be most of your life. The more you understand the system, the better you are at it.
Managing upwards. Keep your manager happy and communicate your work to them.
I'm not suggesting every programmer who works for the likes of Facebook, Exxon, and Comcast quit their jobs. (though, if they did, wouldn't that turn some influential heads in the right direction?) Simply push back when asked to work on something that you feel might cause harm.
People tend to identify themselves with technology they mastered and miss out on all the improvements that happen. This works for a few decades if they're lucky, but someday they're old and wonder why nobody values their skills in an obsolete technology.
We can't all maintain Cobol code bases when we are 50.
There's a particular micro-expression I sometimes notice with people who are working on a software problem. I notice it when something goes wrong unexpectedly.
People who aren't particularly talented at SW development, for a brief instant, give a facial expression of disgust when something crashes or behaves incorrectly. People who are awesome at development, instead, have a look of amusement like they're actually looking forward to see what happened. These facial "micro-expressions" are really fast and subtle, you really have pay attention and it doesn't always work but I've seen it enough times to believe it shows something.
I think this goes back to the impulse to "improve" things that Norvig mentions. You really have to enjoy the act of programming, to be willing to improve on it. It's a kind of feedback loop. Just MHO.
What does that all boil down to? Probably curiosity, practically speaking. If you're genuinely interested in programming, and it's not just about money, status or proving some point, you'll be drawn to learn different things and have different discussions, over the whole course of your career, that will make you a good programmer, rather than just a passible coder.
A caveat: Just as being interested in and liking to play a sport won't get you to play at the top levels without talent as well, there are lots of programmer's jobs that will be out of reach, but others WILL be in reach.
You waste more time defending something that will always need updates and fixes than you do getting things done when you lack humility. It is something I learned early on and I hope more developers learn it.
I will take a 'good enough' dev with a wonderful personality over an above and beyond developer with the most toxic personality any day of the week, unless I'm under an extremely tight deadline. A toxic developer can poison a whole team and ruin their productivity.
To be an engineer one must love to learn, learn fast and be able to learn on his own. It's not a job where you can expect to get training, it's a profession where you must be able to do some of the growing by yourself. It's a constant stream of new tech and new business domain knowledge. Here reading skills are absolutely required: a lot of questions can simply be answered by the relevant man page or by finding a reliable source for whatever knowledge is required for the task. You'll effectively have to become a domain expert several times in a career.
Systematic thinking and pattern recognition are essential skills to have. Our industry creates buzzwords every month and new fads in programming languages and frameworks but most core concepts remain unchanged since their inception.
Logic is absolutely required, and the ability to use the scientific method. This is crucial when debugging where you'll have to observe a problem, collect data on state, formulate an hypothesis on what caused the invalid state and verify your hypothesis. There's no "big picture" here, and every detail matters when doing this so in practice an engineers will often have to be able to keep the whole state of the system in his mind and step through it.
Communication skills are great to have; they effectively allow you to delegate and help colleagues onboard to whatever you are working on faster. From an outside point of view it's effectively super-powers, and if you want to play the politics game, allows you to get the best engineers to want to work with you.
I spend a lot of time reading the writing of other programmers. I've read 4 page documents that are a slog and 20 page documents that are a joy. Your writing, in a lot of cases, will be people's first impression of you, NOT your code.
1) Literacy. You have to know how to read (and ideally write in) your native language at a relatively high level. So much of our craft's knowledge is written down, in technical if not arcane terms, that in order to learn you really have to read.
2) The ability to reason about causes and effects, that is, to envision in your head what the computer will do when it evaluates a statement in your program. Also, the ability to back-reason which statements will produce a desired effect. You need to be able to predict what will happen before you write the code and test it out after the code is written. You'd be surprised how few people have this ability developed and how hard programming is for the general population as a consequence.
3) The ability to be humble and stay focused. Your program will take much longer to write than you think it will, and there will be more bugs. You have to have the diligence and passion to see it through.
If you can do that, the rest of the techniques can be learned with time and effort.
When making changes to an existing system (whether its adding new functionality, extending existing functionality, or refactoring the code while maintaining existing functionality), try to understand the intent behind the current structure of the code and why certain design choices were made.
Once you understand that, you can add new features/extend existing features using the same design OR refactor the code with a new design without impacting existing functionality (assuming you don't have universal test coverage... which frankly will be the case a lot of the time).
Another tactic I use is verbalizing my design choices before/during the implementation of a feature/product. When programming, a lot of developers create a mental structure/map of the code base and what changes they are implementing. They know the changes they are making in their mind and know how to execute them. However, if they were to explain what they were doing to another developer (for collaboration, handoff, etc) or to business/product (ie. in order to explain estimations), they freeze up. Verbalizing your design choice will strengthen your technical communication skills.
Those 2 things aren't necessarily skills, but they are tactics that can be used to be a better programmer.
Better: I try to build things that are sturdier, more beautiful, and solves the problem better.
Faster: Each time I build something, it has to be done faster. Code is faster to read, modify, replicate. Code functions more predictably and is quicker to debug.
Cheaper: I'll keep charging more, but it will cost less. A fresh graduate might do the same for $2000/month, 3 months. I try to get it done in $9000/month, 10 days. Part of this is not spending too much time on something that might be scrapped later, knowing when to plan ahead and when not to.
The essential skills are not really math or writing. Some of it is raw technical ability - know when and how to use reactive programming, declarative, imperative, and so on. Sometimes it's leadership, speaking up when you're stuck or something looks pointless. Sometimes it's just knowing how to learn and unlearn, and how to filter out the golden bits of knowledge from the sea of useless, self-promoting articles and books out there. And it seems trivial, but one of the skills that lets you do all three is knowing how to type 20 WPMs faster and use keyboard shortcuts.
This is really really really hard to do, since we are mostly lazy beings who rather click 50 arrow up key to find the one important command than remembering it or just dont mind to repeat a mundane process without finding a shortcut to do it faster. Programmers who I met that manage to finish a task in 10 minutes instead of 1 day usually have this trait. But I guess this applies to other jobs as well ¯\_(ツ)_/¯
Btw, I used to work as a part timer at my university department. One day one of the staff ask me to reformat about 90 Excels document to her desire format, she spend 10 minutes showing me how to type them out one by one. After this, I went to setup Python environment in that computer and google how to read excel docs. In a few hours I have finish the work that what would took me more than half a day to finish.
The best programmers have an eye for detail that can see below the surface of a system. When someone says "we need feature X because Y", they take a Socratic stance and ask "Why do they believe X will solve Y? Why is there a Y? Is there also a Z or a W to consider?" These aren't necessarily coding questions, they're engineering and process questions. Anyone with some familiarity with a system and the tools can add feature X, but the best developers will think about the precursors and implications of X first in hopes of improving the system as a whole.
Do not accept "magical" behaviour.
I came across quite some projects which had Cypress E2E tests which were, according to the developers, "unstable".
So what is the magic part which makes it fail? There is no such thing as an instable test as such in a test environment, in this case it was a broken test with unmocked data which occasionally threw errors, depending on the OS and speed of the machine it was running on.
In another scenario the was a random number involved, which randomly chose a picture in the test development and depending wether it needed cropping or not, an additional popup would open.
I was told: "well, sometimes it works, sometimes it doesn't". Nobody actually investigated further, tests were excluded instead. Noone ever looked at the artifacts/screenshots/logs.
Always investigate, there is a reason for every "magical" behaviour.
To be a programmer you need the direct hard skills of coding literacy, analytical and logical thinking, combined with enough grit and creativity to see a problem through to completion. If you have that, you'll be a decent programmer, but you may not be a good engineer.
Engineering requires the maturity of thought to consider your actions and your solution over time. It requires more wholistic thinking and not just from the tech architecture point of view. Human soft skills tend to be more important over these time scales: communication, empathy, humility, courage. It's these skills that sustain success.
[1] https://www.oreilly.com/library/view/software-engineering-at...
What resonates with me is the sheer persistence of these learners in the face of the rediculous complexity.
I learned basic at < 10 yo but there wasn’t much to it i the 80s on a home computer. No browsers. No closures. No NPM. No errors because “Yer on Windows”.
You have people doing freecodecamp pushing arch other along, many self taught getting complex apps working with React. Starting from no experience.
So yes keep on going when you hit a wall, struggle through it, and the next thing, and same shit for the job interviews.
Persistence and a love of learning are essential and it’s horrible working with coders that don’t have this trait.
Also:
* team work
* emotional intelligence
* testing and quality
* understanding the business impact
* humility - it’s a skill!
* estimation
* pushing back
* job interview skills
* career strategy (I suck at!)
* going wide and learning lots of things
* going deep in some things
* communication
* inquisitiveness
* getting things done / staving off perfectionism
* some ui/ux awareness
* cloud architecture basics or sys admin basics
* and that’s not all! Etc. etc.
All of which you’ll definitely learn on the job so no need to stress :-)
When my kids were little I thought I would teach them programming. The biggest problem I had was teaching them what a variable was. They finally did figure it out after a lot of work.
Abstraction is the same barrier between elementary school math and algebra. Some people never do learn algebra.
you need to be curious about why things in a certain way or why they don’t work, to take them apart, to continuously ask why
along with curiosity you need to learn. ALL THE TIME. you job learning is never done. there are fundamental things that will not change with time but a lot of things will and mastering anything will be a lot of work.
and last: growth. you need to tackle bigger and bigger problems and understand more and more in order to not get into a dead end career-wise. your goal is that by learning basic building blocks (programming languages, frameworks, tools) you get to work on or learn more advanced building blocks. the abstraction level you work on should go up
I'm an outside consultant and I'm often called to fix stuff that other outside consultants built. Pretty much 100% of the time, I am there because somebody was lacking in attention to detail. Whether it is a misplaced semicolon or a 100mbit interface in a virtual switch or some doodad doing a TCP handshake in the wrong order, I think over half of the 'edge cases' that make it to me are because somebody did not cross their Is and dot their Ts.
I think that good attention to detail is essential not just in programming or systems, but every technical profession.
I think that good programmers also have a better than average short-term working memory space, so they can keep relatively complex structures in their head.
For me, a good programmer realizes that "everything is code". Like, sometimes it's easy to think X problem is too hard for me or I don't have enough experience or this bug is unfixable but end of the day, it's all just code. You can change it however you want and if someone else did implemented something before, it's highly likely that you'll be able to do the same. Having a level of distance from the code one writes really helps.
Competence in engineering and architecture come from expanding the capabilities of your mind to simulate more complex programs and to think in abstractions.
I would say it comes down to a character attribute, and a simple skill. The attribute is curiosity - why does something do what it does, and the simple skill is how to google. That's it. I've seen the most traditionally under-qualified people become excellent, simply by always asking why, and trying to find a answer.
In other words:
- Empathy
- Listening
- Communicating
- Collaborating
- Abstract thinking
It depends on the problem domain. If you're writing low level code for a microcontroller that might require you to be able to do problemsolving on a whole other level than say writing CSS or arranging pre-built React components in a modern web application. In the same way styling those components might require a very different skillset in terms of taste, A/B testing etc.
That can be interpreted as reading someone else's code, but even more importantly: Just being able to understand plain English (or whatever human language).
I've seen so much code that used an API incorrectly, or misunderstood (or simply ignored) documentation. Being able to RTFM, imo, is essential. See also: Understanding what your boss wants and delivering it.
After the inception of stackexchange, the ability (or motivation) to read man pages seems to have have plummeted.
At many times during the process the formation isn’t expressed in code yet, so it’s up to the mind of the programmer to keep the pieces fitting together as intended until the code can be written and take a little bit of the lift from the programmers brain to expressed code.
The essential skill to look for is the ability to imagine some system working differently from how it works right now. A good engineer should be able to imagine several novel, alternative states and compare them, thinking of various consequences and trade-offs.
If you're just trying to be a hobbyist and do stuff for fun then I'd say you need some things that aren't necessarily skills like curiosity, a love of challenging problems, and ability to easily retain information that you read.
- Selecting good names
- And thinking straight forward, being able to count from zero to one and two and so on.
And no, it is not just a joke, but my actual opinion, that understanding the underlying machinery, communicating well, and being to able to think on your own through complicated matters are the most valuable skills in programming.
[edited layout]
also, knowing how to say "no" professionally and firmly is an important and respected skill.
finally, being able to see the forest through the trees and value the business side of what you're doing is a key perspective. Everyone loves to trash talk Sales/Marketing/Management but those people turn your programming into your paycheck so a little understanding is deserved.
Being able to create mental metaphors of systems or problems, solve the metaphors and apply the solution to the original problem.
problem decomposition is maybe not the central skill, but the one that helped me most so far.
Second would be the ability to write a one-page summary of problem and proposed solution.
Work smart, not hard.
I think it also helps if you have a skill for quickly deducing what's wrong when there is an error.
So being able to troubleshoot an error or bug quickly is my favorite coding super power.
Being able to Google a solution or something close to your coding problem/challenge and being able to adapt it and make it your own is a huge plus as well.
If you think about it, software is driven by business requirements in most cases. But business requirements are open to interpretation. How do we know what people really want? This comes down to good communication.
Sincere interest is.
2) Aptitude